#ifndef T_AUTOMA_MODULES_SLAVES_THERMAL_THERMAL_PROTOTYPE_HPP
#define T_AUTOMA_MODULES_SLAVES_THERMAL_THERMAL_PROTOTYPE_HPP

#include "../general/generalPrototype.hpp"
#include "Protocol/commands/ThermalCurve.hpp"

struct ThermalSlave :GeneralSlave {
	struct ThermalMisc {
		//float defaultRampRate = 1;
		// to set heating/cooling modes for now
		float lastTempSet = -300;
	} _thermalMisc;

	ThermalSlave();
	// template copy
	ThermalSlave(ThermalSlave* ref);
	~ThermalSlave();

	int init(GeneralSlave* ref);
	int release();

	void deactivate();

	//int connect(int discoverMode);
	ThermalSlave* connectOneLikeMe();

	int configStandAloneResHeaterWithFanCooler();
	int setLocation(const char* locIn);
	int isThermalControlSupported(const char* modeNameIn);

	int logConnectStart();
	int logConnectSuccess();
	int logConnectComplete();

	long setTempCtrlCurve(float* tempcelsiuses, float* rampRates, int* holdSeconds, int pointNum, float surrounding = 25);
	long setTempCtrlCurve(TempCtrlCurveRL& curveRef, float surrounding = 25);
	long autoAdjustTempCtrlCurve(TempCtrlCurveRL& curveRef, float surrounding = 25);
	int startSchedule();
	int readOut(uint64_t index = 0) override;
	// -1: no action; 0: pause; 1: active
	int updateScheduleProgress(int attemptToPause);
	int abortSchedule();

	virtual void protocolStartReset();

	void recordReading();
	void setNewRecordFile(std::wstring filename);
	int writeToRecordFile(bool newFile);

	int setOnlineSimu(int flag);
	int setSpOb(int flag);
	int simuStart(float rate);
	clock_t getReadings(float* heatBed, float* container, float* pump, float* controller, float* surrounding, std::vector<float>* additional);
	void getScheduleProgress(int* sectionIdx, int* subsectionIdx, int* sectionNum, float* targetTemp);
	int getScheduleProgressX(int exeMin, int exeMax);

	int stopOutput();

	std::wstring summarizeSchedule(int indent);

	int queueCommand(std::wstring cmd, int para0);
	int queueSetCommand(std::wstring cmd, std::wstring para0);
	//int issueCommand();

	std::wstring getOutputModeMajor();
	std::wstring getOutputModeMinor();
private:
	//const int LogPaddingSectionTitle = 2;
	//const int LogPaddingSubSectionTitle = 4;
	//const int LogPaddingMain = 6;
	struct ThermalSimu {
		float updateRate = 1.0f;
		int section = -1;
		int subSection = 0;
	}_thermalSimu;

	TempCtrlCurve _ctrlCurve, _lastCurve;

	struct Readings {
		// Idle, Cool, Heat
		std::string stateOutputMode;
		// Chrg, Hold
		std::string  stateDriveMode;
		// as in master
		clock_t readOutTimeMs;
		// as in slave
		clock_t executionTimeMs;
		float heatBedTemp = -300;
		float containerTemp = -300;
		float pumpTemp = -300;
		float controllerTemp = -300;
		float surroundingTemp = -300;
		std::vector<float> additionalTemps;

		void init();
		void randFromRoom25C(unsigned int seed = 0);
		int randDriveTowards(float targetTemp, float rampUpRate, int timeElapseRate, float changeLimit);
		//clock_t randDriveHold(float targetTemp, int timeElapseRate);
		void randDropTowardsRoom25C(int timeElapseRate);
		int simulateReading(float& temp, float target, float rampRate, float expTempDiff, float rangeRange);
		bool fromStr(std::string& reply);
	} _latestReading;
	std::vector<Readings> records;

	struct SimuState {
		clock_t simuCurvePtReachedTime = 0;
	}_simuStat;

	void updateAfterConnectAny(HandShakeProtocol* protocol);

	int activateTempCtrlCurveSection();
	int simuReadOut();

	/*
	Logging interface and vars implemented in each class to make them distinguished
	*/
	void writeLogLine(std::wstring line, bool withTime = true);
	void writeLogLine(std::string line, bool withTime = true);
	LogBlockCtrl makeLogBlock(const std::wstring& blockName);
	LogBlockCtrl* makeLogBlockPtr(const std::wstring& blockName);
	struct LogMisc {
		std::wstring groupIndentStr;
		std::wstring* getIndentRef() { return &groupIndentStr; };
		LogBlockCtrl* connectLogBlock = nullptr;
		LogBlockCtrl* sectionLogBlock = nullptr;
		LogBlockCtrl* subsectionLogBlock = nullptr;
	}_logMisc;
};
#endif